﻿using System;
using System.Collections.Generic;
using System.Text;

namespace X3DLib
{
    public class Water : ParticleSystem
    {
        //新增底层节点的定义
        /// <summary>
        /// 定义水体的底部EvelationGrid结构，根据range属性来设计
        /// </summary>
        /// <returns></returns>
        public object defWaterBase()
        {
            //ProtoInterface
            ProtoInterface pi = new ProtoInterface();
            /*粒子的各种属性可以通过如下接口输入，从而实现粒子的静态属性的设置*/
            //Material 属性
            pi.addChildren(new field("position", "SFVec3f", "inputOutput"));//设置位置
            pi.addChildren(new field("ambientIntensity", "SFFloat", "inputOutput"));
            pi.addChildren(new field("diffuseColor", "SFColor", "inputOutput"));
            pi.addChildren(new field("emissiveColor", "SFColor", "inputOutput"));
            pi.addChildren(new field("shininess", "SFFloat", "inputOutput"));
            pi.addChildren(new field("specularColor", "SFColor", "inputOutput"));
            pi.addChildren(new field("transparency", "SFFloat", "inputOutput"));
            //定义Grid的set_height节点为了可以实时控制Grid格点的height通过实例而不是节点定义本身
            pi.addChildren("<!--to make it possible for nodes changing grid' heights and easy to set points heights-->\n");
            pi.addChildren("<!--the only Url of grid can be input_changing-->\n");
            pi.addChildren(new field("height", "MFFloat"));
            pi.addChildren("<!--to change the grid params-->\n");
            pi.addChildren(new field("xD", "SFInt32"));
            pi.addChildren(new field("xS", "SFFloat"));
            pi.addChildren(new field("zD", "SFInt32"));
            pi.addChildren(new field("zS", "SFFloat"));
            pi.addChildren("<!--to flag if touch-->\n");
            pi.addChildren(new field("touch_is", "SFBool"));
            pi.addChildren("<!--to get the posotion be touched-->\n");
            pi.addChildren(new field("touch_pos", "SFVec3f"));
            //ProtoBody add group
            ProtoBody pb = new ProtoBody();
            //定义节点的body_group
            Group g = new Group();
            pb.addChildren(g);
            //节点定义的外层transform
            Transform t = new Transform();
            t.DEF = "waterbase_t1";
            IS is_tp = new IS();
            is_tp.addChildren(new connect("translation", "position"));
            t.addChildren(is_tp);

            Shape shape = new Shape();
            //添加质材
            Material m = new Material();
            IS is_mdc = new IS();
            is_mdc.addChildren(new connect("ambientIntensity", "ambientIntensity"));
            is_mdc.addChildren(new connect("diffuseColor", "diffuseColor"));
            is_mdc.addChildren(new connect("emissiveColor", "emissiveColor"));
            is_mdc.addChildren(new connect("shininess", "shininess"));
            is_mdc.addChildren(new connect("specularColor", "specularColor"));
            is_mdc.addChildren(new connect("transparency", "transparency"));
            m.addChildren(is_mdc);
            Appearance app = new Appearance(m);
            app.addChildren(new ImageTexture("3.jpg"));
            shape.appearance = app;

            //加入原型节点
            ElevationGrid grid=new ElevationGrid("waterbase_Grid");
            IS grid_is=new IS ();
            grid_is .addChildren (new connect ("set_height","height"));
            grid.addChildren (grid_is);
            shape.addChildren(grid);

            t.addChildren(shape);
            t.addChildren(new TouchSensor("waterbase_touch"));
            //添加脚本
            t.addChildren(createWBScript());
            g.addChildren(t);
            //添加路由
            TimeSensor time = new TimeSensor("waterbase_clock", "1", "true");
            ROUTE route_start = new ROUTE("fraction_changed", time.DEF, "start", "waterbase_control");
            //是否touch
            ROUTE route_touch_is = new ROUTE("isActive", "waterbase_touch", "touch_change", "waterbase_control");
            //touch位置改变
            ROUTE route_touch_pos = new ROUTE("hitPoint_changed", "waterbase_touch", "touch_position", "waterbase_control");
            g.addChildren(time);
            g.addChildren(route_start);
            g.addChildren(route_touch_is);
            g.addChildren(route_touch_pos);
            
            Group pd_g = new Group();
            pd_g.DEF = "declare_waterbase";//包裹整个节点定义

            ProtoDeclare pd = new ProtoDeclare(pb, pi);//节点定义
            pd.name = "WaterBase_Node";
            pd_g.addChildren(pd);

            return pd_g;
        }
        /// <summary>
        /// 为水体节点创建脚本
        /// </summary>
        /// <returns></returns>
        public object createWBScript()
        {
            Script s = new Script();
            s.DEF = "waterbase_control";
            s.directOutput = "true";
            //设置节点关联节点原型
            field grid = new field("grid", "SFNode", "inputOutput");
            grid.addChildren(new ElevationGrid() { USE = "waterbase_Grid" });
            s.addChildren(grid);
            //设置Grid参数field
            s.addChildren(new field("xD", "SFInt32"));
            s.addChildren(new field("xS", "SFFloat"));
            s.addChildren(new field("zD", "SFInt32"));
            s.addChildren(new field("zS", "SFFloat"));
            //设置touch信息
            s.addChildren(new field("touch_is", "SFBool"));
            s.addChildren(new field("touch_pos", "SFVec3f"));
            //设置关联interface->script fields
            IS inf2scf = new IS();
            inf2scf.addChildren("<!--as follow field just can be initialized so they can't be changed by interface input directly-->\n");
            inf2scf.addChildren(new connect("xD", "xD"));
            inf2scf.addChildren(new connect("xS", "xS"));
            inf2scf.addChildren(new connect("zD", "zD"));
            inf2scf.addChildren(new connect("zS", "zS"));
            inf2scf.addChildren("<!--get out the touch position-->\n");
            inf2scf.addChildren(new connect("touch_is", "touch_is"));
            inf2scf.addChildren(new connect("touch_pos", "touch_pos"));

            s.addChildren(inf2scf);
            //启动函数
            s.addChildren(new field("start", "SFFloat", "inputOnly"));
            //触碰函数
            s.addChildren(new field("touch_change", "SFBool","inputOnly"));
            s.addChildren(new field("touch_position", "SFVec3f","inputOnly"));
            //添加脚本函数
            s.addChildren(new WaterScriptFactor.WaterBaseScript().waterbase());//只要实现了setScriptContext()
            return s;
        }
        /// <summary>
        /// 重写初始化方法来实现子类的参数设置
        /// </summary>
        public override void initialize()
        {
            this.nodeName = "Water";
            this.color = "1 1 1";
            this.range = "7 2 7";
            this.life = "200";
            this.num = "1";//debuging
        }
        /// <summary>
        /// 重写方法来添加新建节点实例
        /// </summary>
        /// <param name="instanceGroup"></param>
        public override void addSubclassProtoInstances(ref Transform instanceGroup)
        {
            //base.addSubclassProtoInstance(ref instanceGroup);
            instanceGroup.addChildren(new ProtoInstance("WaterBase_Node"));
        }
        /// <summary>
        /// 重写方法来为脚本添加field节点
        /// </summary>
        /// <param name="s"></param>
        public override void addSubClassScriptFields(ref Script s)
        {
            //base.addSubClassScriptFields(ref s);
            s.addChildren("<!--this array of int32 carry every gridpoint's time-->\n");
            s.addChildren(new field("GridTimeArray", "MFInt32"));
            s.addChildren("<!--remember the count of free particles-->\n");
            s.addChildren(new field("FreeNum", "SFInt32"));
            s.addChildren("<!--this array of int32 carry all free particles index -->\n");
            s.addChildren(new field("FreePartArray", "MFInt32"));
            s.addChildren(new field("xD", "SFInt32"));
            s.addChildren(new field("zD", "SFInt32"));
        }
        /// <summary>
        /// 重写节点来设置粒子系统的动作控制脚本
        /// </summary>
        /// <returns></returns>
        public override string createSubClassScript()
        {
            
            //this.addChildren(defWaterBase());//增加水的底层接本节点
            WaterScriptFactor.WaterBaseScript script = new WaterScriptFactor.WaterBaseScript();
            //this.addChildren(new Background() { skyColor = "1 1 1" });
            return script.waterWithBaseMain();
        }
        public override void addSubClassNodes()
        {
            this.addChildren(new Background() { skyColor = "1 1 1" });
            this.addChildren (defWaterBase());
        }
    }
}
